home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
176-200
/
disk_193
/
zc
/
p2.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-06
|
14KB
|
843 lines
/* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to redistribute it freely, with the
* following restrictions:
* 1) No charge may be made other than reasonable charges for reproduction.
* 2) Modified versions must be clearly marked as such.
* 3) The authors are not responsible for any harmful consequences
* of using this software, even if they result from defects in it.
*
* p2.c
*
* Expression tree routines.
*
* Constant folding, typing of nodes, simple transformations.
*/
#include <stdio.h>
#include "param.h"
#include "tok.h"
#include "nodes.h"
#include "cookie.h"
#if MMCC
overlay "pass2"
#endif
extern int xflags[];
#define debug xflags['t'-'a']
extern nmerrors;
NODEP bas_type();
do_expr(np, cookie)
NODE *np;
{
if (np == NULL)
return;
/* include if want only one error at a time
if (nmerrors) {
freenode(np);
return;
}
*/
p2_expr(&np);
genx(np, cookie);
}
p2_expr(npp)
NODEP *npp;
{
NODEP np = *npp;
if (np == NULL) return;
if (debug > 1) {
printf("P2 enter");
printnode(np);
}
confold(npp,0);
np = *npp;
form_types(np);
if (debug) {
printf("p2_expr");
printnode(np);
}
return;
}
form_types(np)
NODEP np;
{
if (np == NULL) return;
switch (np->e_type) {
case E_SPEC:
switch (np->e_token) { /* special cases */
case '.':
case ARROW:
form_types(np->n_left);
sel_type(np);
return;
case '(':
if (np->n_right) {
form_types(np->n_right); /* args */
np->e_type = E_BIN;
} else
np->e_type = E_UNARY;
fun_type(np);
return;
}
/* fall through */
case E_BIN:
form_types(np->n_left);
form_types(np->n_right);
b_types(np);
break;
case E_UNARY:
form_types(np->n_left);
u_types(np);
break;
case E_LEAF:
l_types(np);
break;
}
}
/* (fun) (args) */
fun_type(np)
NODEP np;
{
NODEP lp, typ;
NODEP allsyms(), new_fun();
lp = np->n_left;
if (lp->e_token == ID) { /* may be new ID */
typ = allsyms(lp);
if (typ == NULL)
typ = new_fun(lp);
typ = typ->n_tptr;
lp->n_tptr = typ;
lp->n_flags |= N_COPYT;
} else {
form_types(lp);
typ = lp->n_tptr;
}
if (typ->t_token != '(') { /* fun ret ? */
error("call non-fun");
goto bad;
}
typ = typ->n_tptr;
goto good;
bad:
typ = bas_type(K_INT);
good:
np->n_tptr = typ;
np->n_flags |= N_COPYT;
}
/* (struct|union) (. or ->) ID */
sel_type(xp)
NODEP xp;
{
NODEP np, sup;
int tok;
NODEP rv;
NODEP llook();
np = xp->n_right;
sup = xp->n_left->n_tptr;
tok = xp->e_token;
/* already checked that np->e_token == ID */
if (tok == ARROW) {
if (sup->t_token != STAR) {
error("(non pointer)->");
goto bad;
}
sup = sup->n_tptr;
}
if (sup->t_token != K_STRUCT && sup->t_token != K_UNION) {
error("select non-struct");
goto bad;
}
rv = llook(sup->n_right, np);
if (rv == NULL) {
error("? member ID");
goto bad;
}
xp->e_offs = rv->e_offs;
if (rv->e_fldw) {
xp->e_fldw = rv->e_fldw;
xp->e_fldo = rv->e_fldo;
}
rv = rv->n_tptr;
goto good;
bad:
rv = bas_type(K_INT);
good:
xp->n_tptr = rv;
xp->n_flags |= N_COPYT;
/* change to UNARY op */
xp->e_type = E_UNARY;
freenode(np);
xp->n_right = NULL;
/* change ARY OF to PTR TO */
if (rv->t_token == '[')
see_array(xp);
}
l_types(np)
register NODE *np;
{
NODEP allsyms();
register NODE *tp;
switch (np->e_token) {
case ID: /* already did see_id */
if (np->n_tptr->t_token == '[') /* change to &ID */
see_array(np);
return;
case ICON:
tp = bas_type(icon_ty(np));
break;
case FCON:
tp = bas_type(K_DOUBLE);
break;
case SCON:
tp = bas_type(SCON);
break;
default:
errors("Weird leaf",np->n_name);
bad:
tp = bas_type(K_INT);
}
np->n_tptr = tp;
np->n_flags |= N_COPYT;
}
u_types(np)
NODEP np;
{
NODEP tp;
NODEP lp = np->n_left;
NODEP normalty();
tp = lp->n_tptr; /* default */
switch (np->e_token) {
case DOUBLE '+':
case DOUBLE '-':
case POSTINC:
case POSTDEC:
mustlval(lp);
mustty(lp, R_SCALAR);
if (tp->t_token == STAR)
np->e_offs = tp->n_tptr->t_size;
else
np->e_offs = 1;
break;
case STAR:
if (mustty(lp, R_POINTER)) goto bad;
tp = tp->n_tptr;
np->n_tptr = tp;
np->n_flags |= N_COPYT;
/* Ary of to Ptr to */
if (tp->t_token == '[')
see_array(np);
return;
case UNARY '&':
mustlval(lp);
tp = allocnode();
tp->n_tptr = lp->n_tptr;
tp->n_flags |= N_COPYT;
tp->t_token = STAR;
sprintf(tp->n_name, "Ptr to");
tp->t_size = SIZE_P;
np->n_tptr = tp;
return; /* no COPYT */
case UNARY '-':
mustty(lp, R_ARITH);
tp = normalty(lp, NULL);
break;
case TCONV:
mustty(lp, R_SCALAR);
if (np->n_tptr->t_token != K_VOID)
mustty(np, R_SCALAR);
return; /* type already specified */
case '!':
mustty(lp, R_SCALAR);
tp = bas_type(K_INT);
break;
case '~':
mustty(lp, R_INTEGRAL);
tp = normalty(lp, NULL);
break;
default:
error("bad unary type");
bad:
tp = bas_type(K_INT);
}
np->n_tptr = tp;
np->n_flags |= N_COPYT;
}
b_types(np)
NODEP np;
{
NODEP tp;
NODEP lp, rp;
NODEP normalty(), addty(), colonty();
int op;
op = np->e_token;
if (isassign(op)) {
mustlval(np->n_left);
op -= (ASSIGN 0);
}
lp = np->n_left;
rp = np->n_right;
tp = bas_type(K_INT);
switch (op) {
case '*':
case '/':
mustty(lp, R_ARITH);
mustty(rp, R_ARITH);
tp = normalty(lp,rp);
break;
case '%':
case '&':
case '|':
case '^':
mustty(lp, R_INTEGRAL);
mustty(rp, R_INTEGRAL);
tp = normalty(lp,rp);
break;
case '+':
case '-':
mustty(lp, R_SCALAR);
mustty(rp, R_SCALAR);
tp = addty(np);
break;
case DOUBLE '<':
case DOUBLE '>':
mustty(lp, R_INTEGRAL);
mustty(rp, R_INTEGRAL);
tp = normalty(lp, NULL);
break;
case '<':
case '>':
case LTEQ:
case GTEQ:
case DOUBLE '=':
case NOTEQ:
mustty(lp, R_SCALAR);
mustty(rp, R_SCALAR);
chkcmp(np);
break; /* INT */
case DOUBLE '&':
case DOUBLE '|':
mustty(lp, R_SCALAR);
mustty(rp, R_SCALAR);
break; /* INT */
case '?':
mustty(lp, R_SCALAR);
tp = rp->n_tptr;
break;
case ':':
if (same_type(lp->n_tptr, rp->n_tptr)) {
tp = lp->n_tptr;
break;
}
mustty(lp, R_SCALAR);
mustty(rp, R_SCALAR);
tp = colonty(np);
break;
case '=':
mustlval(lp);
mustty(lp, R_ASSN);
asn_chk(lp->n_tptr, rp);
tp = lp->n_tptr;
break;
case ',':
tp = rp->n_tptr;
break;
default:
error("bad binary type");
bad:
tp = bas_type(K_INT);
}
if (isassign(np->e_token)) {
/* ignore normal result -- result is left type */
tp = lp->n_tptr;
}
np->n_tptr = tp;
np->n_flags |= N_COPYT;
}
long
conlval(np)
NODEP np;
{
long i;
confold(&np,0);
if (np->e_token == ICON) {
i = np->e_ival;
freenode(np);
return i;
}
error("need const expr");
return 0;
}
conxval(np)
NODEP np;
{
return (int)conlval(np);
}
confold(npp,spec)
NODEP *npp;
{
NODEP np;
NODEP tp, onp;
int tok,spl,spr;
long l;
np = *npp;
if (np == NULL) return;
switch (np->e_type) {
case E_LEAF:
lcanon(np,spec);
return;
case E_UNARY:
confold(&np->n_left,0);
ucanon(np);
return;
case E_BIN:
confold(&np->n_left,0);
confold(&np->n_right,0);
if (np->e_token == '?') {
tok = np->n_left->e_token;
if (tok != ICON)
return;
l = np->n_left->e_ival;
onp = np;
tp = np->n_right; /* ':' node */
if (l) { /* take true side */
np = tp->n_left;
tp->n_left = NULL;
} else { /* take false side */
np = tp->n_right;
tp->n_right = NULL;
}
freenode(onp);
*npp = np;
return;
}
bcanon(np);
if (np->e_flags & C_AND_A)
b_assoc(np);
return;
case E_SPEC:
tok = np->e_token;
spl = spr = 0;
switch (tok) {
case '(':
spl = tok; /* new name allowed */
break;
case '.':
case ARROW:
spr = tok; /* look in struct sym.tab. */
break;
}
confold(&np->n_left,spl);
confold(&np->n_right,spr);
return;
}
}
newicon(np,x,nf)
NODE *np;
long x;
{
np->e_token = ICON;
np->e_ival = x;
np->e_flags = nf;
sprintf(np->n_name, "%ld", x);
np->e_type = E_LEAF;
if (np->n_left) {
freenode(np->n_left);
np->n_left = NULL;
}
if (np->n_right) {
freenode(np->n_right);
np->n_right = NULL;
}
}
newfcon(np,x,nf)
NODE *np;
double x;
{
np->e_token = FCON;
np->e_fval = x;
np->e_flags = nf;
sprintf(np->n_name, FLTFORM, x);
np->e_type = E_LEAF;
if (np->n_left) {
freenode(np->n_left);
np->n_left = NULL;
}
if (np->n_right) {
freenode(np->n_right);
np->n_right = NULL;
}
}
/* LEAF */
/* sptok is token if E_SPEC node is parent
and dont want to look at ID yet */
lcanon(np,sptok)
NODE *np;
{
NODE *tp;
NODEP allsyms();
long x;
if (np->e_token == ID) {
if (sptok)
return;
see_id(np);
return;
}
if (np->e_token == TSIZEOF) {
tp = np->n_tptr;
x = tp->t_size;
np->n_tptr = NULL;
if ((np->n_flags & N_COPYT) == 0)
freenode(tp);
newicon(np, x, 0);
}
}
/* UNARY */
ucanon(np)
NODE *np;
{
NODE *tp;
long x,l;
int lflags = 0;
if (np->e_token == K_SIZEOF) {
tp = np->n_left;
confold(&tp,0);
form_types(tp);
tp = tp->n_tptr;
x = tp->t_size;
goto out;
}
if (np->n_left->e_token == FCON) {
if (np->e_token == UNARY '-')
newfcon(np, -(np->n_left->e_fval));
return;
}
if (np->n_left->e_token != ICON)
return;
l = np->n_left->e_ival;
lflags = np->n_left->e_flags;
switch (np->e_token) {
case UNARY '-':
x = -l; break;
case '~':
x = ~l; break;
case '!':
x = !l; break;
default:
return;
}
out:
newicon(np, x, lflags);
}
bcanon(np)
register NODE *np;
{
int ltok, rtok;
double l,r;
NODEP tp;
ltok = np->n_left->e_token;
rtok = np->n_right->e_token;
if (ltok != ICON && ltok != FCON)
return;
if (rtok != ICON && rtok != FCON) {
/* left is ?CON, right is not */
if (np->e_flags & (C_AND_A|C_NOT_A)) {
/* reverse sides - put CON on right */
tp = np->n_left;
np->n_left = np->n_right;
np->n_right = tp;
if (np->e_flags & C_NOT_A)
swt_op(np);
}
return;
}
if (ltok == ICON && rtok == ICON) {
b2i(np);
return;
}
if (ltok == FCON)
l = np->n_left->e_fval;
else
l = (double)np->n_left->e_ival;
if (rtok == FCON)
r = np->n_right->e_fval;
else
r = (double)np->n_right->e_ival;
b2f(np,l,r);
}
/* canon for assoc. & comm. op */
/* this code will almost never be executed, but it was fun. */
b_assoc(np)
NODEP np;
{
NODEP lp, rp;
int tok;
lp = np->n_left;
if (lp->e_token != np->e_token)
return;
/* left is same op as np */
rp = np->n_right;
tok = lp->n_right->e_token;
if (tok != ICON && tok != FCON)
return;
/* left.right is ?CON */
tok = rp->e_token;
if (tok == ICON || tok == FCON) {
/* have 2 CONS l.r and r -- put together on r */
NODEP ep;
ep = lp->n_left;
np->n_left = ep;
np->n_right = lp;
lp->n_left = rp;
/* can now fold 2 CONS */
bcanon(lp);
} else {
/* have 1 CON at l.r -- move to top right */
NODEP kp;
kp = lp->n_right;
lp->n_right = rp;
np->n_right = kp;
}
}
/* switch pseudo-commutative op */
swt_op(np)
NODEP np;
{
int newtok;
switch (np->e_token) {
case LTEQ: newtok = '>'; break;
case GTEQ: newtok = '<'; break;
case '<': newtok = GTEQ; break;
case '>': newtok = LTEQ; break;
default:
return;
}
np->e_token = newtok;
}
/* BINARY 2 ICON's */
b2i(np)
register NODE *np;
{
register long l,r,x;
int newflags,lflags;
newflags = 0;
r = np->n_right->e_ival;
newflags = np->n_right->e_flags;
l = np->n_left->e_ival;
lflags = np->n_left->e_flags;
newflags = newflags>lflags ? newflags : lflags;
switch (np->e_token) {
case '+':
x = l+r; break;
case '-':
x = l-r; break;
case '*':
x = l*r; break;
case '/':
x = l/r; break;
case '%':
x = l%r; break;
case '>':
x = l>r; break;
case '<':
x = l<r; break;
case LTEQ:
x = l>=r; break;
case GTEQ:
x = l<=r; break;
case DOUBLE '=':
x = l==r; break;
case NOTEQ:
x = l!=r; break;
case '&':
x = l&r; break;
case '|':
x = l|r; break;
case '^':
x = l^r; break;
case DOUBLE '<':
x = l<<r; break;
case DOUBLE '>':
x = l>>r; break;
default:
return;
}
newicon(np, x, newflags);
}
/* BINARY 2 FCON's */
b2f(np,l,r)
register NODE *np;
double l,r;
{
register double x;
int ix, isint;
isint = 0;
switch (np->e_token) {
case '+':
x = l+r; break;
case '-':
x = l-r; break;
case '*':
x = l*r; break;
case '/':
x = l/r; break;
case '>':
ix = l>r; isint++; break;
case '<':
ix = l<r; isint++; break;
case LTEQ:
ix = l>=r; isint++; break;
case GTEQ:
ix = l<=r; isint++; break;
case DOUBLE '=':
ix = l==r; isint++; break;
case NOTEQ:
ix = l!=r; isint++; break;
default:
return;
}
if (isint)
newicon(np, (long)ix, 0);
else
newfcon(np, x);
}
same_type(a,b)
register NODE *a, *b;
{
more:
if (a == b)
return 1;
if (a == NULL || b == NULL)
return 0;
if (a->t_token != b->t_token)
return 0;
if (a->t_token != STAR && a->t_size != b->t_size)
return 0;
a = a->n_tptr;
b = b->n_tptr;
goto more;
}
see_id(np)
NODEP np;
{
NODEP tp;
NODEP allsyms(), def_type();
tp = allsyms(np);
if (tp == NULL) {
errorn("undefined:", np);
tp = def_type();
goto out;
}
switch (tp->e_sc) {
case ENUM_SC:
newicon(np, tp->e_ival, 0);
return;
case K_REGISTER:
np->e_rno = tp->e_rno;
/* fall through */
default:
np->e_sc = tp->e_sc;
np->e_offs = tp->e_offs;
tp = tp->n_tptr;
}
out:
np->n_tptr = tp;
np->n_flags |= N_COPYT;
/* special conversions */
if (tp->t_token == '(')
insptrto(np);
}
insptrto(np)
NODEP np;
{
NODEP op, copyone();
op = copyone(np);
np->n_left = op;
np->e_token = UNARY '&';
np->e_type = E_UNARY;
strcpy(np->n_name, "&fun");
np->n_flags &= ~N_COPYT;
}
/* np points to ID or STAR or '.' node
tptr is a COPY
tptr token is '[' */
see_array(np)
NODEP np;
{
NODEP tp, copyone();
tp = copyone(np);
tp->n_left = np->n_left;
tp->n_tptr = tp->n_tptr->n_tptr;
np->n_left = tp;
np->e_token = UNARY '&';
np->e_type = E_UNARY;
strcpy(np->n_name, "&ary");
arytoptr(np);
/* leave old size
np->n_tptr->t_size = SIZE_P;
*/
}